home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 2 / Amiga Tools 2.iso / tools / vim / src / main.c < prev    next >
C/C++ Source or Header  |  1995-03-09  |  15KB  |  561 lines

  1. /* vi:ts=4:sw=4
  2.  *
  3.  * VIM - Vi IMproved        by Bram Moolenaar
  4.  *
  5.  * Read the file "credits.txt" for a list of people who contributed.
  6.  * Read the file "uganda.txt" for copying and usage conditions.
  7.  */
  8.  
  9. #define EXTERN
  10. #include "vim.h"
  11. #include "globals.h"
  12. #include "proto.h"
  13. #include "param.h"
  14.  
  15. #ifdef SPAWNO
  16. # include <spawno.h>            /* special MSDOS swapping library */
  17. #endif
  18.  
  19. static void usage __PARMS((int));
  20.  
  21.     static void
  22. usage(n)
  23.     int n;
  24. {
  25.     register int i;
  26.     static char_u *(use[]) = {(char_u *)"[file ..]\n",
  27.                             (char_u *)"-t tag\n",
  28.                             (char_u *)"-e [errorfile]\n"};
  29.     static char_u *(errors[]) =  {(char_u *)"Unknown option\n",        /* 0 */
  30.                                 (char_u *)"Too many arguments\n",    /* 1 */
  31.                                 (char_u *)"Argument missing\n",        /* 2 */
  32.                                 };
  33.  
  34.     fprintf(stderr, (char *)errors[n]);
  35.     fprintf(stderr, "usage:");
  36.     for (i = 0; ; ++i)
  37.     {
  38.         fprintf(stderr, " vim [options] ");
  39.         fprintf(stderr, (char *)use[i]);
  40.         if (i == (sizeof(use) / sizeof(char_u *)) - 1)
  41.             break;
  42.         fprintf(stderr, "   or:");
  43.     }
  44.     fprintf(stderr, "\noptions:\t-v\t\treadonly mode (view)\n");
  45.     fprintf(stderr, "\t\t-n\t\tno swap file, use memory only\n");
  46.     fprintf(stderr, "\t\t-b\t\tbinary mode\n");
  47.     fprintf(stderr, "\t\t-r\t\trecovery mode\n");
  48. #ifdef AMIGA
  49.     fprintf(stderr, "\t\t-x\t\tdon't use newcli to open window\n");
  50.     fprintf(stderr, "\t\t-d device\tuse device for I/O\n");
  51. #endif
  52.     fprintf(stderr, "\t\t-T terminal\tset terminal type\n");
  53.     fprintf(stderr, "\t\t-o[N]\t\topen N windows (def: one for each file)\n");
  54.     fprintf(stderr, "\t\t+\t\tstart at end of file\n");
  55.     fprintf(stderr, "\t\t+lnum\t\tstart at line lnum\n");
  56.     fprintf(stderr, "\t\t-c command\texecute command first\n");
  57.     fprintf(stderr, "\t\t-s scriptin\tread commands from script file\n");
  58.     fprintf(stderr, "\t\t-w scriptout\twrite commands in script file\n");
  59.     mch_windexit(1);
  60. }
  61.  
  62. #ifdef USE_LOCALE
  63. # include <locale.h>
  64. #endif
  65.  
  66.     void
  67. main(argc, argv)
  68.     int                argc;
  69.     char          **argv;
  70. {
  71.     char_u           *initstr;        /* init string from the environment */
  72.     char_u           *term = NULL;    /* specified terminal name */
  73.     char_u           *fname = NULL;    /* file name from command line */
  74.     char_u           *command = NULL;    /* command from + or -c option */
  75.     char_u           *tagname = NULL;    /* tag from -t option */
  76.     int             c;
  77.     int                doqf = 0;
  78.     int                i;
  79.     int                bin_mode = FALSE;    /* -b option used */
  80.     int                win_count = 1;        /* number of windows to use */
  81.  
  82. #ifdef USE_LOCALE
  83.     setlocale(LC_ALL, "");        /* for ctype() and the like */
  84. #endif
  85.  
  86. /*
  87.  * Check if we have an interactive window.
  88.  * If not, open one with a newcli command (needed for :! to work).
  89.  * check_win will also handle the -d argument (for the Amiga).
  90.  */
  91.     check_win(argc, argv);
  92.  
  93. /*
  94.  * allocate the first window and buffer. Can't to anything without it
  95.  */
  96.     if ((curwin = win_alloc(NULL)) == NULL ||
  97.             (curbuf = buflist_new(NULL, NULL, 1L, FALSE)) == NULL)
  98.         mch_windexit(0);
  99.     curwin->w_buffer = curbuf;
  100.  
  101. /*
  102.  * If the executable is called "view" we start in readonly mode.
  103.  */
  104.     if (STRCMP(gettail((char_u *)argv[0]), (char_u *)"view") == 0)
  105.     {
  106.         readonlymode = TRUE;
  107.         curbuf->b_p_ro = TRUE;
  108.         p_uc = 0;
  109.     }
  110.  
  111.     ++argv;
  112.     /*
  113.      * Process the command line arguments
  114.      *        '-c {command}'    execute command
  115.      *        '+{command}'    execute command
  116.      *         '-s scriptin'    read from script file
  117.      *        '-w scriptout'    write to script file
  118.      *        '-v'            view
  119.      *        '-b'            binary
  120.      *        '-n'            no .vim file
  121.      *        '-r'            recovery mode
  122.      *        '-x'            open window directly, not with newcli
  123.      *        '-o[N]'            open N windows (default: number of files)
  124.      *        '-T terminal'    terminal name
  125.      */
  126.     while (argc > 1 && ((c = argv[0][0]) == '+' || (c == '-' &&
  127.             strchr("vnbrxocswTd", c = argv[0][1]) != NULL && c != NUL)))
  128.     {
  129.         --argc;
  130.         switch (c)
  131.         {
  132.         case '+':             /* + or +{number} or +/{pat} or +{command} */
  133.             c = argv[0][1];
  134.             if (c == NUL)
  135.                 command = (char_u *)"$";
  136.             else
  137.                 command = (char_u *)&(argv[0][1]);
  138.             break;
  139.  
  140.         case 'v':
  141.             readonlymode = TRUE;
  142.             curbuf->b_p_ro = TRUE;
  143.             /*FALLTHROUGH*/
  144.  
  145.         case 'n':
  146.             p_uc = 0;
  147.             break;
  148.  
  149.         case 'b':
  150.             bin_mode = TRUE;        /* postpone to after reading .exrc files */
  151.             break;
  152.  
  153.         case 'r':
  154.             recoverymode = 1;
  155.             break;
  156.         
  157.         case 'x':
  158.             break;    /* This is ignored as it is handled in check_win() */
  159.  
  160.         case 'o':
  161.             c = argv[0][2];
  162.             if (c != NUL && !isdigit(c))
  163.             {
  164.                 fprintf(stderr, "-o option needs numeric argument (or none)\n");
  165.                 mch_windexit(2);
  166.             }
  167.             win_count = atoi(&(argv[0][2]));        /* 0 means: number of files */
  168.             break;
  169.  
  170.         default:    /* options with argument */
  171.             ++argv;
  172.             --argc;
  173.             if (argc < 1)
  174.                 usage(2);
  175.  
  176.             switch (c)
  177.             {
  178.             case 'c':            /* -c {command} */
  179.                 command = (char_u *)&(argv[0][0]);
  180.                 break;
  181.  
  182.             case 's':
  183.                 if ((scriptin[0] = fopen(argv[0], READBIN)) == NULL)
  184.                 {
  185.                     fprintf(stderr, "cannot open %s for reading\n", argv[0]);
  186.                     mch_windexit(2);
  187.                 }
  188.                 break;
  189.             
  190.             case 'w':
  191.                 if ((scriptout = fopen(argv[0], APPENDBIN)) == NULL)
  192.                 {
  193.                     fprintf(stderr, "cannot open %s for output\n", argv[0]);
  194.                     mch_windexit(2);
  195.                 }
  196.                 break;
  197.  
  198. /*
  199.  * The -T term option is always available and when TERMCAP is supported it
  200.  * overrides the environment variable TERM.
  201.  */
  202.             case 'T':
  203.                 term = (char_u *)*argv;
  204.                 break;
  205.             
  206.         /*    case 'd':        This is ignored as it is handled in check_win() */
  207.             }
  208.         }
  209.         ++argv;
  210.     }
  211.  
  212.     /*
  213.      * Allocate space for the generic buffers
  214.      */
  215.     if ((IObuff = alloc(IOSIZE)) == NULL || (NameBuff = alloc(MAXPATHL)) == NULL)
  216.         mch_windexit(0);
  217.  
  218.     /* note that we may use mch_windexit() before mch_windinit()! */
  219.     mch_windinit();
  220.     set_init();                    /* after mch_windinit because Rows is used */
  221.     firstwin->w_height = Rows - 1;
  222.     cmdline_row = Rows - 1;
  223.  
  224.     /*
  225.      * Process the other command line arguments.
  226.      */
  227.     if (argc > 1)
  228.     {
  229.         c = argv[0][1];
  230.         switch (argv[0][0])
  231.         {
  232.           case '-':
  233.             switch (c)
  234.             {
  235.               case 'e':            /* -e QuickFix mode */
  236.                 switch (argc)
  237.                 {
  238.                     case 2:
  239.                             if (argv[0][2])        /* -eerrorfile */
  240.                                 p_ef = (char_u *)argv[0] + 2;
  241.                             break;                /* -e */
  242.  
  243.                     case 3:                        /* -e errorfile */
  244.                             ++argv;
  245.                             p_ef = (char_u *)argv[0];
  246.                             break;
  247.  
  248.                     default:                    /* argc > 3: too many arguments */
  249.                             usage(1);
  250.                 }
  251.                 doqf = 1;
  252.                 break;
  253.  
  254.             case 't':            /* -t tag  or -ttag */
  255.                 switch (argc)
  256.                 {
  257.                     case 2:
  258.                             if (argv[0][2])        /* -ttag */
  259.                             {
  260.                                 tagname = (char_u *)argv[0] + 2;
  261.                                 break;
  262.                             }
  263.                             usage(2);            /* argument missing */
  264.                             break;
  265.  
  266.                     case 3:                        /* -t tag */
  267.                             ++argv;
  268.                             tagname = (char_u *)argv[0];
  269.                             break;
  270.  
  271.                     default:                    /* argc > 3: too many arguments */
  272.                             usage(1);
  273.                 }
  274.                 break;
  275.  
  276.             default:
  277.                 usage(0);
  278.             }
  279.             break;
  280.  
  281.           default:                /* must be a file name */
  282. #if !defined(UNIX) || defined(ARCHIE)
  283.             if (ExpandWildCards(argc - 1, (char_u **)argv, &arg_count,
  284.                     &arg_files, TRUE, TRUE) == OK && arg_count != 0)
  285.             {
  286.                 fname = arg_files[0];
  287.                 arg_exp = TRUE;
  288.             }
  289. #else
  290.             arg_files = (char_u **)argv;
  291.             arg_count = argc - 1;
  292.             fname = (char_u *)argv[0];
  293. #endif
  294.             if (arg_count > 1)
  295.                 printf("%d files to edit\n", arg_count);
  296.             break;
  297.         }
  298.     }
  299.  
  300.     RedrawingDisabled = TRUE;
  301.  
  302.     curbuf->b_nwindows = 1;        /* there is one window */
  303.     win_init(curwin);            /* init cursor position */
  304.     init_yank();                /* init yank buffers */
  305.     termcapinit(term);            /* get terminal capabilities */
  306.     screenclear();                /* clear screen (just inits screen structures,
  307.                                     because starting is TRUE) */
  308.  
  309. #ifdef MSDOS /* default mapping for some often used keys */
  310.     domap(0, "#1 :help\r", NORMAL);            /* F1 is help key */
  311.     domap(0, "\316R i", NORMAL);            /* INSERT is 'i' */
  312.     domap(0, "\316S \177", NORMAL);            /* DELETE is 0x7f */
  313.     domap(0, "\316G 0", NORMAL);            /* HOME is '0' */
  314.     domap(0, "\316w H", NORMAL);            /* CTRL-HOME is 'H' */
  315.     domap(0, "\316O $", NORMAL);            /* END is '$' */
  316.     domap(0, "\316u L", NORMAL);            /* CTRL-END is 'L' */
  317.     domap(0, "\316I \002", NORMAL);            /* PageUp is '^B' */
  318.     domap(0, "\316\204 1G", NORMAL);        /* CTRL-PageUp is '1G' */
  319.     domap(0, "\316Q \006", NORMAL);            /* PageDown is '^F' */
  320.     domap(0, "\316v G", NORMAL);            /* CTRL-PageDown is 'G' */
  321.             /* insert mode */
  322.     domap(0, "#1 \017:help\r", INSERT);        /* F1 is help key */
  323.     domap(0, "\316R \033", INSERT);            /* INSERT is ESC */
  324.             /* note: extra space needed to avoid the same memory used for this
  325.                and the one above, domap() will add a NUL to it */
  326.     domap(0, "\316S  \177", INSERT+CMDLINE);    /* DELETE is 0x7f */
  327.     domap(0, "\316G \017""0", INSERT);        /* HOME is '^O0' */
  328.     domap(0, "\316w \017H", INSERT);        /* CTRL-HOME is '^OH' */
  329.     domap(0, "\316O \017$", INSERT);        /* END is '^O$' */
  330.     domap(0, "\316u \017L", INSERT);        /* CTRL-END is '^OL' */
  331.     domap(0, "\316I \017\002", INSERT);        /* PageUp is '^O^B' */
  332.     domap(0, "\316\204 \017\061G", INSERT);    /* CTRL-PageUp is '^O1G' */
  333.     domap(0, "\316Q \017\006", INSERT);        /* PageDown is '^O^F' */
  334.     domap(0, "\316v \017G", INSERT);        /* CTRL-PageDown is '^OG' */
  335. #endif
  336.  
  337.     msg_start();        /* in case a mapping is printed */
  338.     no_wait_return = TRUE;
  339.  
  340. /*
  341.  * get system wide defaults (for unix)
  342.  */
  343. #ifdef DEFVIMRC_FILE
  344.     (void)dosource(DEFVIMRC_FILE);
  345. #endif
  346.  
  347. /*
  348.  * Try to read initialization commands from the following places:
  349.  * - environment variable VIMINIT
  350.  * - file s:.vimrc ($HOME/.vimrc for Unix)
  351.  * - environment variable EXINIT
  352.  * - file s:.exrc ($HOME/.exrc for Unix)
  353.  * The first that exists is used, the rest is ignored.
  354.  */
  355.     if ((initstr = vimgetenv((char_u *)"VIMINIT")) != NULL)
  356.         docmdline(initstr);
  357.     else if (dosource((char_u *)SYSVIMRC_FILE) == FAIL)
  358.     {
  359.         if ((initstr = vimgetenv((char_u *)"EXINIT")) != NULL)
  360.             docmdline(initstr);
  361.         else
  362.             (void)dosource((char_u *)SYSEXRC_FILE);
  363.     }
  364.  
  365. /*
  366.  * Read initialization commands from ".vimrc" or ".exrc" in current directory.
  367.  * This is only done if the 'exrc' option is set.
  368.  * Because of security reasons we disallow shell and write commands now,
  369.  * except for unix if the file is owned by the user or 'secure' option has been
  370.  * reset in environmet of global ".exrc" or ".vimrc".
  371.  * Only do this if VIMRC_FILE is not the same as SYSVIMRC_FILE or DEFVIMRC_FILE.
  372.  */
  373.     if (p_exrc)
  374.     {
  375. #ifdef UNIX
  376.         {
  377.             struct stat s;
  378.  
  379.                 /* if ".vimrc" file is not owned by user, set 'secure' mode */
  380.             if (stat(VIMRC_FILE, &s) || s.st_uid != getuid())
  381.                 secure = p_secure;
  382.         }
  383. #else
  384.         secure = p_secure;
  385. #endif
  386.  
  387.         i = FAIL;
  388.         if (fullpathcmp((char_u *)SYSVIMRC_FILE, (char_u *)VIMRC_FILE)
  389. #ifdef DEFVIMRC_FILE
  390.                 && fullpathcmp((char_u *)DEFVIMRC_FILE, (char_u *)VIMRC_FILE)
  391. #endif
  392.                 )
  393.             i = dosource((char_u *)VIMRC_FILE);
  394. #ifdef UNIX
  395.         if (i == FAIL)
  396.         {
  397.             struct stat s;
  398.  
  399.                 /* if ".exrc" file is not owned by user set 'secure' mode */
  400.             if (stat(EXRC_FILE, &s) || s.st_uid != getuid())
  401.                 secure = p_secure;
  402.             else
  403.                 secure = 0;
  404.         }
  405. #endif
  406.         if (i == FAIL && fullpathcmp((char_u *)SYSEXRC_FILE, (char_u *)EXRC_FILE))
  407.             (void)dosource((char_u *)EXRC_FILE);
  408.     }
  409.  
  410. #ifdef SPAWNO            /* special MSDOS swapping library */
  411.     init_SPAWNO("", SWAP_ANY);
  412. #endif
  413. /*
  414.  * Call settmode and starttermcap here, so the T_KS and T_TS may be defined
  415.  * by termcapinit and redifined in .exrc.
  416.  */
  417.     settmode(1);
  418.     starttermcap();
  419.  
  420.     no_wait_return = FALSE;
  421.         /* done something that is not allowed or error message */
  422.     if (secure == 2 || need_wait_return)
  423.         wait_return(TRUE);        /* must be called after settmode(1) */
  424.     secure = 0;
  425.  
  426.     if (bin_mode)                    /* -b option used */
  427.     {
  428.         curbuf->b_p_bin = 1;        /* binary file I/O */
  429.         curbuf->b_p_tw = 0;            /* no automatic line wrap */
  430.         curbuf->b_p_wm = 0;            /* no automatic line wrap */
  431.         curbuf->b_p_tx = 0;            /* no text mode */
  432.         p_ta = 0;                    /* no text auto */
  433.         curbuf->b_p_ml = 0;            /* no modelines */
  434.         curbuf->b_p_et = 0;            /* no expand tab */
  435.     }
  436.  
  437.     (void)setfname(fname, NULL, TRUE);
  438.     maketitle();
  439.  
  440.     if (win_count == 0)
  441.         win_count = arg_count;
  442.     if (win_count > 1)
  443.         win_count = make_windows(win_count);
  444.     else
  445.         win_count = 1;
  446.  
  447. /*
  448.  * Start putting things on the screen.
  449.  * Scroll screen down before drawing over it
  450.  * Clear screen now, so file message will not be cleared.
  451.  */
  452.     starting = FALSE;
  453.     if (T_CVV != NULL && *T_CVV)
  454.     {
  455.         outstr(T_CVV);
  456.         outstr(T_CV);
  457.     }
  458.     screenclear();                        /* clear screen */
  459.  
  460.     if (recoverymode)                    /* do recover */
  461.     {
  462.         if (ml_open() == FAIL)            /* Initialize storage structure */
  463.             getout(1);
  464.         ml_recover();
  465.     }
  466.     else
  467.         (void)open_buffer();            /* create memfile and read file */
  468.  
  469.     setpcmark();
  470.  
  471.     if (doqf && qf_init() == FAIL)        /* if reading error file fails: exit */
  472.         mch_windexit(3);
  473.  
  474.     /*
  475.      * If opened more than one window, start editing files in the other windows.
  476.      * Make_windows() has already opened the windows.
  477.      * This is all done by putting commands in the stuff buffer.
  478.      */
  479.     for (i = 1; i < win_count; ++i)
  480.     {
  481.         if (curwin->w_next == NULL)            /* just checking */
  482.             break;
  483.         win_enter(curwin->w_next, FALSE);
  484.                                             /* edit file i, if there is one */
  485.         (void)doecmd(i < arg_count ? arg_files[i] : NULL,
  486.                                             NULL, NULL, TRUE, (linenr_t)1);
  487.         curwin->w_arg_idx = i;
  488.     }
  489.     win_enter(firstwin, FALSE);                /* back to first window */
  490.  
  491.     /*
  492.      * If there are more file names in the argument list than windows,
  493.      * put the rest of the names in the buffer list.
  494.      */
  495.     for (i = win_count; i < arg_count; ++i)
  496.         (void)buflist_add(arg_files[i]);
  497.  
  498.     if (command)
  499.         docmdline(command);
  500.     /*
  501.      * put the :ta command in the stuff buffer here, so that it will not
  502.      * be erased by an emsg().
  503.      */
  504.     if (tagname)
  505.     {
  506.         stuffReadbuff((char_u *)":ta ");
  507.         stuffReadbuff(tagname);
  508.         stuffReadbuff((char_u *)"\n");
  509.     }
  510.  
  511.     RedrawingDisabled = FALSE;
  512.     updateScreen(NOT_VALID);
  513.  
  514.         /* start in insert mode (already taken care of for :ta command) */
  515.     if (p_im && stuff_empty())
  516.         stuffReadbuff((char_u *)"i");
  517. /*
  518.  * main command loop
  519.  */
  520.     for (;;)
  521.     {
  522.         if (got_int)
  523.         {
  524.             (void)vgetc();                /* flush all buffers */
  525.             got_int = FALSE;
  526.         }
  527.         adjust_cursor();                /* put cursor on an existing line */
  528.         if (skip_redraw)                /* skip redraw (for ":" in wait_return()) */
  529.             skip_redraw = FALSE;
  530.         else if (stuff_empty())            /* only when no command pending */
  531.         {
  532.             cursupdate();                /* Figure out where the cursor is based
  533.                                             on curwin->w_cursor. */
  534.             if (VIsual.lnum)
  535.                 updateScreen(INVERTED);    /* update inverted part */
  536.             if (must_redraw)
  537.                 updateScreen(must_redraw);
  538.             if (keep_msg)
  539.                 msg(keep_msg);            /* display message after redraw */
  540.  
  541.             showruler(FALSE);
  542.  
  543.             setcursor();
  544.             cursor_on();
  545.         }
  546.  
  547.         normal();                        /* get and execute a command */
  548.     }
  549.     /*NOTREACHED*/
  550. }
  551.  
  552.     void
  553. getout(r)
  554.     int             r;
  555. {
  556.     windgoto((int)Rows - 1, 0);
  557.     outchar('\r');
  558.     outchar('\n');
  559.     mch_windexit(r);
  560. }
  561.